package cn.easyutil.util.javaUtil;

import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.JPEGTranscoder;

import cn.easyutil.util.javaUtil.bean.MergeImageBean;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;

/**
 * 图片工具类
 *
 * @author spc
 */
public class ImageUtil {

    /**
     * 二维码颜色
     */
    private static final int BLACK = 0xFF000000;
    /**
     * 二维码颜色
     */
    private static final int WHITE = 0xFFFFFFFF;

    /**
     * 字体类型：普通，加粗，斜体，粗斜体
     */
    private static int[] fontType = {Font.PLAIN, Font.BOLD, Font.ITALIC, Font.BOLD + Font.ITALIC};
    /**
     * 获取系统中可用的字体
     */
    private static String[] fonts = {"宋体"};
    /**
     * 二维码图片格式
     */
    private static final List<String> IMAGE_TYPE = new ArrayList<String>();

    static {
        IMAGE_TYPE.add("jpg");
        IMAGE_TYPE.add("png");
        IMAGE_TYPE.add("jpeg");
    }

    /**
     * 根据提供的文本生成二维码(默认大小300*300)
     *
     * @param text        二维码内容
     * @param outFilePath 输出目录
     */
    public static void creatQRcode(String text, String outFilePath) {
        creatQRcode(text, null, outFilePath, 300);
    }

    /**
     * 根据提供的文本生成二维码(默认大小300*300)
     *
     * @param text        二维码内容
     * @param logoPath    二维码中心logo图片路径
     * @param outFilePath 输出目录
     */
    public static void creatQRcode(String text, String logoPath, String outFilePath) {
        creatQRcode(text, logoPath, outFilePath, 300);
    }

    /**
     * 生成二维码
     *
     * @param text        二维码内容
     * @param logoPath    二维码中心logo图片路径
     * @param outFilePath 输出目录
     * @param size        二维码大小
     */
    public static void creatQRcode(String text, String logoPath, String outFilePath, int size) {
        creatQRcode(text, logoPath, outFilePath, size, null);
    }

    /**
     * 根据提供的文本生成二维码(默认大小300*300)
     *
     * @param text     二维码内容
     * @param response 输出到客户端
     */
    public static void creatQRcode(String text, HttpServletResponse response) {
        creatQRcode(text, null, null, 300, response);
    }

    /**
     * 根据提供的文本生成二维码(默认大小300*300)
     *
     * @param text     二维码内容
     * @param logoPath 二维码中心logo图片路径
     * @param response 输出到客户端
     */
    public static void creatQRcode(String text, String logoPath, HttpServletResponse response) {
        creatQRcode(text, logoPath, null, 300, response);
    }

    /**
     * 生成二维码
     *
     * @param text     二维码内容
     * @param logoPath 二维码中心logo图片路径
     * @param size     二维码大小
     * @param response 输出到客户端
     */
    public static void creatQRcode(String text, String logoPath, HttpServletResponse response, int size) {
        creatQRcode(text, logoPath, null, size, response);
    }

    /**
     * 生成二维码
     *
     * @param text        二维码内容
     * @param logoPath    二维码中心logo图片路径
     * @param outFilePath 输出目录
     * @param size        二维码大小
     * @param response    输出到客户端
     */
    private static void creatQRcode(String text, String logoPath, String outFilePath, int size,
                                    HttpServletResponse response) {
        BufferedImage image = creatQRcode(text, size, logoPath);
        if (outFilePath != null && !outFilePath.equals("")) {
            File file = new File(outFilePath);
            try {
                ImageIO.write(image, "png", file);
                LoggerUtil.debug(ImageUtil.class, "QR code create success");
            } catch (IOException e) {
                LoggerUtil.error(ImageUtil.class, "QR code create failed", e);
            }
            return;
        }
        if (response != null) {
            try {
                ImageIO.write(image, "png", response.getOutputStream());
                response.getOutputStream().flush();
                LoggerUtil.debug(ImageUtil.class, "QR code create success");
            } catch (IOException e) {
                LoggerUtil.error(ImageUtil.class, "QR code create failed", e);
            }
            return;
        }
        throw new NullPointerException("output of the QR code must not be null");
    }

    /**
     * 二维码流的形式，包含文本内容
     *
     * @param text     二维码文本内容
     * @param size     二维码图片大小,null为默认300*300
     * @param logoPath 二维码中心logo图片地址,null为不生成logo
     * @return 二维码图片输出流
     */
    public static BufferedImage creatQRcode(String text, Integer size, String logoPath) {
        // 默认图片大小300*300
        if (size == null || size <= 0) {
            size = 300;
        }
        BufferedImage image = null;
        try {
            // 设置编码字符集
            Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
            // 设置编码
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            // 设置容错率最高
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            hints.put(EncodeHintType.MARGIN, 1);
            // 1、生成二维码
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            BitMatrix bitMatrix = multiFormatWriter.encode(text, BarcodeFormat.QR_CODE, size, size, hints);

            // 2、获取二维码宽高
            int codeWidth = bitMatrix.getWidth();
            int codeHeight = bitMatrix.getHeight();

            // 3、将二维码放入缓冲流
            image = new BufferedImage(codeWidth, codeHeight, BufferedImage.TYPE_INT_RGB);

            for (int i = 0; i < codeWidth; i++) {
                for (int j = 0; j < codeHeight; j++) {
                    // 4、循环将二维码内容定入图片
                    image.setRGB(i, j, bitMatrix.get(i, j) ? BLACK : WHITE);
                }
            }

            // 判断是否写入logo图片
            // 1.zxing方式生成二维码 注意： 1,文本生成二维码的方法独立出来,返回image流的形式,可以输出到页面
            // 2,设置容错率为最高,一般容错率越高,图片越不清晰,但是只有设置高一点才能兼容logo图片
            // 3,logo图片默认占二维码图片的20%,设置太大会导致无法解析
            if (logoPath != null && !"".equals(logoPath)) {
                File logoPic = new File(logoPath);
                if (logoPic.exists()) {
                    Graphics2D g = image.createGraphics();
                    BufferedImage logo = ImageIO.read(logoPic);
                    int widthLogo = logo.getWidth(null) > image.getWidth() * 2 / 10 ? (image.getWidth() * 2 / 10)
                            : logo.getWidth(null);
                    int heightLogo = logo.getHeight(null) > image.getHeight() * 2 / 10 ? (image.getHeight() * 2 / 10)
                            : logo.getHeight(null);
                    int x = (image.getWidth() - widthLogo) / 2;
                    int y = (image.getHeight() - heightLogo) / 2;

                    // 开始绘制图片
                    g.drawImage(logo, x, y, widthLogo, heightLogo, null);
                    g.drawRoundRect(x, y, widthLogo, heightLogo, 15, 15);
                    // 边框宽度
                    g.setStroke(new BasicStroke(2));
                    // 边框颜色
                    g.setColor(Color.WHITE);
                    g.drawRect(x, y, widthLogo, heightLogo);

                    g.dispose();
                    logo.flush();
                    image.flush();
                }
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return image;

    }

    /**
     * 解析二维码
     * <p>
     * 图片路径
     *
     * @return 二维码内容
     */
    public static String readQRcode(BufferedImage image) {
        try {
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            Binarizer binarizer = new HybridBinarizer(source);
            BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
            Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
            hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
            Result result = new MultiFormatReader().decode(binaryBitmap, hints);// 对图像进行解码
            return result.getText();
        } catch (NotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 解析本地二维码图片
     *
     * @param filePath 文件路径
     * @return
     */
    public static String readQRcode(String filePath) {
        try {
            BufferedImage image = ImageIO.read(new File(filePath));
            return readQRcode(image);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 解析二维码输入流
     *
     * @param input 输入流
     * @return
     */
    public static String readQRcode(InputStream input) {
        try {
            BufferedImage image = ImageIO.read(input);
            return readQRcode(image);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 生成指定验证码图像文件
     *
     * @param filePath 输出目录
     * @param code     验证码
     */
    public static void createVerificationCode(String filePath, String code) {
        createVerificationCode(0, 0, filePath, code);
    }

    /**
     * 生成指定验证码图像文件
     *
     * @param response
     * @param code     验证码
     */
    public static void createVerificationCode(HttpServletResponse response, String code) {
        createVerificationCode(0, 0, response, code);
    }

    /**
     * 生成指定验证码图像文件
     *
     * @param w        宽度
     * @param h        高度
     * @param response
     * @param code     验证码
     */
    public static void createVerificationCode(int w, int h, HttpServletResponse response, String code) {
        BufferedImage img = outputImage(w, h, code);
        if (response != null) {
            try {
                ImageIO.write(img, "PNG", response.getOutputStream());
                LoggerUtil.info(ImageUtil.class, "verification code [" + code + "] export success");
                return;
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                try {
                    response.getOutputStream().flush();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    /**
     * 生成指定验证码图像文件
     *
     * @param w    宽度
     * @param h    高度
     *             输出目录
     * @param code 验证码
     */
    public static void createVerificationCode(int w, int h, String filePath, String code) {
        if (filePath == null) {
            return;
        }
        BufferedImage img = outputImage(w, h, code);
        try {
            ImageIO.write(img, "PNG", new File(filePath));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 输出指定验证码图片流
     *
     * @param w
     * @param h
     * @param code
     * @throws IOException
     */
    private static BufferedImage outputImage(int w, int h, String code) {
        if (w <= 0 || h <= 0) {
            int length = 0;
            char[] chars = code.toCharArray();
            for (int i = 0; i < chars.length; i++) {
                if (chars[i] >= 0 && chars[i] <= 127) {
                    length++;
                } else {
                    length += 2;
                }
            }
            w = length * 40;
            h = length * 30 / 4 < 50 ? 50 : length * 30 / 4;
        }
        int verifySize = code.length();
        BufferedImage image = null;
        try {
            image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        Random rand = new Random();
        Graphics2D g2 = image.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        Color[] colors = new Color[5];
        Color[] colorSpaces = new Color[]{Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA,
                Color.ORANGE, Color.PINK, Color.YELLOW};
        float[] fractions = new float[colors.length];
        for (int i = 0; i < colors.length; i++) {
            colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
            fractions[i] = rand.nextFloat();
        }
        Arrays.sort(fractions);

        g2.setColor(Color.GRAY);// 设置边框色
        g2.fillRect(0, 0, w, h);

        Color c = getRandColor(200, 250);
        g2.setColor(c);// 设置背景色
        g2.fillRect(0, 2, w, h - 4);

        // 绘制干扰线
        Random random = new Random();
        g2.setColor(getRandColor(160, 200));// 设置线条的颜色
        for (int i = 0; i < code.length() * 10; i++) {
            int x = random.nextInt(w - 1);
            int y = random.nextInt(h - 1);
            int xl = random.nextInt(6) + 1;
            int yl = random.nextInt(12) + 1;
            g2.drawLine(x, y, x + xl + 40, y + yl + 20);
        }

        // 添加噪点
        float yawpRate = (float) w / 1000;// 噪声率
        int area = (int) (yawpRate * w * h);
        for (int i = 0; i < area; i++) {
            int x = random.nextInt(w);
            int y = random.nextInt(h);
            int rgb = getRandomIntColor();
            image.setRGB(x, y, rgb);
        }

        // shear(g2, w, h, c);// 使图片扭曲

        int fontSize = h - 4;
        char[] chars = code.toCharArray();
        for (int i = 0; i < verifySize; i++) {
            g2.setColor(getRandColor(100, 160));
            Font font = new Font(fonts[new Random().nextInt(fonts.length)],
                    fontType[new Random().nextInt(fontType.length)], fontSize);
            g2.setFont(font);
            AffineTransform affine = new AffineTransform();
            affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1),
                    (w / verifySize) * i + fontSize / 2, h / 2);
            g2.setTransform(affine);
            g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10);
        }

        g2.dispose();
        return image;
    }

    private static Color getRandColor(int fc, int bc) {
        Random random = new Random();
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    private static int getRandomIntColor() {
        int[] rgb = getRandomRgb();
        int color = 0;
        for (int c : rgb) {
            color = color << 8;
            color = color | c;
        }
        return color;
    }

    private static int[] getRandomRgb() {
        Random random = new Random();
        int[] rgb = new int[3];
        for (int i = 0; i < 3; i++) {
            rgb[i] = random.nextInt(255);
        }
        return rgb;
    }

    /**
     * 多张图片合并为一张
     *
     * @param weight 合并后的图片宽度
     * @param height 合并后的图片高度
     * @param li     图片集合
     */
    public static byte[] mergeImage(int weight, int height, List<MergeImageBean> li) {
        // 创建一张图片，并规定大小
        BufferedImage combined = new BufferedImage(weight, height, BufferedImage.TYPE_INT_RGB);
        // 获取图片画板
        Graphics g = combined.getGraphics();
        for (MergeImageBean bean : li) {
            // 依次按配置信息画图
            g.drawImage(bean.getImg(), bean.getX(), bean.getY(), bean.getWeight(), bean.getHeight(), null);
        }
        return imgToByte(combined);
    }

    /**
     * 图片压缩
     *
     * @param but        原图
     * @param targetW    压缩后的宽度
     * @param targetH    压缩后的高度
     * @param equalRatio 是否等比缩放，默认等比
     */
    public static byte[] resize(byte[] but, int targetW, int targetH, boolean... equalRatio) {
        return resize(IOUtil.byteToInput(but), targetW, targetH, equalRatio);
    }

    /**
     * 图片压缩
     *
     * @param in         原图
     * @param targetW    压缩后的宽度
     * @param targetH    压缩后的高度
     * @param equalRatio 是否等比缩放，默认等比
     */
    public static byte[] resize(InputStream in, int targetW, int targetH, boolean... equalRatio) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        if (equalRatio.length == 0) {
            equalRatio = new boolean[]{true};
        }
        try {
            if (equalRatio[0]) {
                if (targetH > targetW) {
                    Thumbnails.of(in).height(targetH).toOutputStream(out);
                } else {
                    Thumbnails.of(in).width(targetW).toOutputStream(out);
                }
            } else {
                Thumbnails.of(in).forceSize(targetW, targetH).toOutputStream(out);
            }
            return out.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 图片压缩
     * <p>
     * 原图
     *
     * @param targetW    压缩后的宽度
     * @param targetH    压缩后的高度
     * @param equalRatio 是否等比缩放，默认等比
     */
    public static byte[] resize(BufferedImage source, int targetW, int targetH, boolean... equalRatio) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        if (equalRatio.length == 0) {
            equalRatio = new boolean[]{true};
        }
        try {
            if (equalRatio[0]) {
                if (targetH > targetW) {
                    Thumbnails.of(source).outputFormat("png").height(targetH).toOutputStream(out);
                } else {
                    Thumbnails.of(source).outputFormat("png").width(targetW).toOutputStream(out);
                }
            } else {
                Thumbnails.of(source).outputFormat("png").forceSize(targetW, targetH).toOutputStream(out);
            }
            return out.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 更改图片类型
     *
     * @param in   图片流
     * @param type 要更改的类型，例:png
     * @return 更改后的图片
     */
    public static byte[] updateImgType(InputStream in, String type) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            Thumbnails.of(in).scale(1.0).outputFormat(type).toOutputStream(out);
            return out.toByteArray();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * SVG格式转PNG
     *
     * @return
     */
    public static byte[] svgToPng(InputStream in) {
        JPEGTranscoder t = new JPEGTranscoder();
        t.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, new Float(.8));
        TranscoderInput input = new TranscoderInput(in);
        ByteArrayOutputStream ostream = new ByteArrayOutputStream();
        TranscoderOutput output = new TranscoderOutput(ostream);
        try {
            t.transcode(input, output);
            ostream.flush();
            return ostream.toByteArray();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 图片转换byte
     *
     * @param source
     * @return
     */
    public static byte[] imgToByte(BufferedImage source) {
        return imgToByte(source, "PNG");
    }

    /**
     * 图片转byte
     *
     * @param source
     * @param formartName
     * @return
     */
    public static byte[] imgToByte(BufferedImage source, String formartName) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] but = null;
        try {
            ImageIO.write(source, formartName, out);
            but = out.toByteArray();
            return but;
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 不改变图片大小使图片变模糊
     *
     * @param in    原图
     * @param scale 模糊值,取值范围0-1,越小越模糊
     * @return
     */
    public static byte[] toBlurred(InputStream in, float scale) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        if (scale > 1) {
            scale = 0.9f;
        }
        if (scale <= 0) {
            scale = 0.01f;
        }
        try {
            Thumbnails.of(in).scale(1.0).outputQuality(scale).toOutputStream(out);
            return out.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 添加水印
     *
     * @param source    要添加水印的图片
     * @param watermark 要添加的水印
     * @param positions 水印位置
     * @return
     */
    public static byte[] addWatermark(InputStream source, InputStream watermark, Positions... positions) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            Thumbnails.of(source)
                    .scale(0.8)
                    .outputQuality(0.8f)
                    .watermark(positions.length > 0 ? positions[0] : Positions.BOTTOM_RIGHT, ImageIO.read(watermark), 0.25f)
                    .toOutputStream(out);
            return out.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 图片流转byte
     *
     * @param in
     * @return
     */
    public static byte[] imgToByte(InputStream in) {
        return IOUtil.inputToByte(in);
    }

    /**
     * byte转图片
     *
     * @param but
     * @return
     */
    public static BufferedImage byteToImg(byte[] but) {
        ByteArrayInputStream in = new ByteArrayInputStream(but);
        try {
            return ImageIO.read(in);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 检查图片是否透明
     *
     * @param in
     * @throws IOException
     * @return true:透明 false
     */
    public static boolean isTransparent(InputStream in) throws IOException {
        BufferedImage bi = (BufferedImage) ImageIO.read(in);
        // 获取图像的宽度和高度
        int width = bi.getWidth();
        int height = bi.getHeight();
        // 扫描图片
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {// 行扫描
                int dip = bi.getRGB(j, i);
                if (dip >> 24 != 0) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 图片流转图片
     *
     * @param in
     * @return
     */
    public static BufferedImage byteToImg(InputStream in) {
        try {
            return ImageIO.read(in);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static BufferedImage createSeal(String companyName, String centerMessage) {
        return createSeal(companyName, centerMessage, null, true);
    }

    public static BufferedImage createSeal(String companyName, String centerMessage, String year, boolean addStar) {
        if (StringUtil.isEmpty(companyName)) {
            throw new RuntimeException("未提供企业名称");
        }
        //默认大小500*500，变动此大小需要动态调整字体大小和位置，暂时未做
        int WIDTH = 500, HEIGHT = 500;
        // 定义图像buffer
        BufferedImage buffImg = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        // 获取Graphics2D
        Graphics2D g2d = buffImg.createGraphics();

        // 增加下面代码使得背景透明
        buffImg = g2d.getDeviceConfiguration().createCompatibleImage(WIDTH, HEIGHT, Transparency.TRANSLUCENT);

        Graphics2D g = buffImg.createGraphics();
        g.setColor(Color.RED);
        //设置锯齿圆滑
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        //绘制圆
        int radius = HEIGHT / 3;//周半径
        int CENTERX = WIDTH / 2;//画图所出位置
        int CENTERY = HEIGHT / 2;//画图所处位置

        Ellipse2D circle = new Ellipse2D.Double();
        circle.setFrameFromCenter(CENTERX, CENTERY, CENTERX + radius, CENTERY + radius);
        g.draw(circle);

        //绘制中间的五角星
        if (addStar) {
            g.setFont(new Font("宋体", Font.BOLD, 120));
            g.drawString("★", CENTERX - (120 / 2), CENTERY + (120 / 3));
        }

        //追加说明
        if (!StringUtil.isEmpty(centerMessage)) {
            char[] chars = centerMessage.toCharArray();
            //当前文本字符数（中文算2个字符）
            int charSize = 0;
            //目前设计的最大允许的字符数(中文7个汉字)
            int maxCharSize = 14;
            //当前写入文本的X坐标
            int drawCenterMessageX = 100;
            for (char c : chars) {
                if (StringUtil.isBaseChar(c)) {
                    charSize++;
                } else {
                    charSize += 2;
                }
            }
            if (charSize < maxCharSize) {
                //需要补充的位数
                int supSize = (maxCharSize - charSize) / 2;
                StringBuffer sb = new StringBuffer();
                while (supSize > 0) {
                    sb.append(" ");
                    supSize--;
                }
                centerMessage = sb.toString() + centerMessage;
            }
            g.setFont(new Font("宋体", Font.LAYOUT_LEFT_TO_RIGHT, 30));// 写入签名
            g.drawString(centerMessage, CENTERX - (drawCenterMessageX), CENTERY + (30 + 50));
        }

        //添加年份
        if (!StringUtil.isEmpty(year)) {
            g.setFont(new Font("宋体", Font.LAYOUT_LEFT_TO_RIGHT, 20));// 写入签名
            g.drawString(year, CENTERX - (60), CENTERY + (30 + 80));
        }


        //根据输入字符串得到字符数组
//        String[] messages2 = companyName.split("", 0);
//        String[] messages = new String[messages2.length - 1];
//        System.arraycopy(messages2, 1, messages, 0, messages2.length - 1);
        String[] messages = companyName.split("", 0);

        //输入的字数
        int ilength = messages.length;

        //设置字体属性
        int fontsize = 40;
        Font f = new Font("Serif", Font.BOLD, fontsize);

        FontRenderContext context = g.getFontRenderContext();
        Rectangle2D bounds = f.getStringBounds(companyName, context);

        //字符宽度＝字符串长度/字符数
        double char_interval = (bounds.getWidth() / ilength);
        //上坡度
        double ascent = -bounds.getY();

        int first = 0, second = 0;
        boolean odd = false;
        if (ilength % 2 == 1) {
            first = (ilength - 1) / 2;
            odd = true;
        } else {
            first = (ilength) / 2 - 1;
            second = (ilength) / 2;
            odd = false;
        }

        double radius2 = radius - ascent;
        double x0 = CENTERX;
        double y0 = CENTERY - radius + ascent;
        //旋转角度
        double a = 2 * Math.asin(char_interval / (2 * radius2));

        if (odd) {
            g.setFont(f);
            g.drawString(messages[first], (float) (x0 - char_interval / 2), (float) y0);

            //中心点的右边
            for (int i = first + 1; i < ilength; i++) {
                double aa = (i - first) * a;
                double ax = radius2 * Math.sin(aa);
                double ay = radius2 - radius2 * Math.cos(aa);
                AffineTransform transform = AffineTransform.getRotateInstance(aa);//,x0 + ax, y0 + ay);
                Font f2 = f.deriveFont(transform);
                g.setFont(f2);
                g.drawString(messages[i], (float) (x0 + ax - char_interval / 2 * Math.cos(aa)), (float) (y0 + ay - char_interval / 2 * Math.sin(aa)));
            }
            //中心点的左边
            for (int i = first - 1; i > -1; i--) {
                double aa = (first - i) * a;
                double ax = radius2 * Math.sin(aa);
                double ay = radius2 - radius2 * Math.cos(aa);
                AffineTransform transform = AffineTransform.getRotateInstance(-aa);//,x0 + ax, y0 + ay);
                Font f2 = f.deriveFont(transform);
                g.setFont(f2);
                g.drawString(messages[i], (float) (x0 - ax - char_interval / 2 * Math.cos(aa)), (float) (y0 + ay + char_interval / 2 * Math.sin(aa)));
            }

        } else {
            //中心点的右边
            for (int i = second; i < ilength; i++) {
                double aa = (i - second + 0.5) * a;
                double ax = radius2 * Math.sin(aa);
                double ay = radius2 - radius2 * Math.cos(aa);
                AffineTransform transform = AffineTransform.getRotateInstance(aa);//,x0 + ax, y0 + ay);
                Font f2 = f.deriveFont(transform);
                g.setFont(f2);
                g.drawString(messages[i], (float) (x0 + ax - char_interval / 2 * Math.cos(aa)), (float) (y0 + ay - char_interval / 2 * Math.sin(aa)));
            }

            //中心点的左边
            for (int i = first; i > -1; i--) {
                double aa = (first - i + 0.5) * a;
                double ax = radius2 * Math.sin(aa);
                double ay = radius2 - radius2 * Math.cos(aa);
                AffineTransform transform = AffineTransform.getRotateInstance(-aa);//,x0 + ax, y0 + ay);
                Font f2 = f.deriveFont(transform);
                g.setFont(f2);
                g.drawString(messages[i], (float) (x0 - ax - char_interval / 2 * Math.cos(aa)), (float) (y0 + ay + char_interval / 2 * Math.sin(aa)));
            }
        }

        return buffImg;
    }

    /**
     * 保存图片
     * @param img
     * @param file
     */
    public static void saveImg(BufferedImage img,File file){
        saveImg(img,"png",file);
    }

    /**
     * 保存图片
     * @param img
     * @param format
     * @param file
     */
    public static void saveImg(BufferedImage img,String format,File file){
        try {
            ImageIO.write(img, format, new FileOutputStream(file));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) throws Exception {
//        saveImg(createSeal("杭州泰基网络有限公司","电子合同专用章"),new File("D://sign.png"));
        File file = new File("D:\\platform-takedata\\chongqinghouse\\房产签名授权\\南投正本.pdf");
        File out = new File("D:\\platform-takedata\\chongqinghouse\\房产签名授权\\nantou.jpg");
        PDFUtil.pdfToImage(new FileInputStream(file),new FileOutputStream(out),100);
    }
}
